#ifndef CORE_BUFFER_HPP_
#define CORE_BUFFER_HPP_

#include "base_export.hpp"
#include "base_fwd.hpp"
#include "blob.hpp"
#include "result.hpp"

TB_NAMESPACE_BEGIN

class TB_BASE_API MemoryBuffer {
 public:
  MemoryBuffer();
  explicit MemoryBuffer(const std::string& data);
  MemoryBuffer(const char* data, uint32 len);
  ~MemoryBuffer();
  Blob Merge() const;
  void Swap(MemoryBuffer& buf);
  void Reserve(uint32 len);
	void Reset();
  uint32 Size() const;
	uint32 BlobCapacity() const; 
  void Shrink();
  void WriteBytes(MemoryBuffer&, uint32 len);
  void WriteBytes(const char* data, uint32 len);
  void WriteValue(const char* data, uint32 len);
  void PrependBytes(const char* data, uint32 len);
  void PrependValue(const char* data, uint32 len);
  bool SeekRead(uint32 pos);
  void SkipRead(uint32 len);
  bool SeekWrite(uint32 pos);
  Result PeekBytes(uint32 len, char* data);
  Result ReadBytes(uint32 len, char* data);
  Result ReadBytes(uint32 len, MemoryBuffer&);
  tuple<const char*, uint32> ReadBytes();
	tuple<const char*, uint32> PeekBytes(uint32 len);
  Blob ReadBytes(uint32 len);
	const char* ReadValue(uint32 len);
  uint32 ReadIndex() const;
  uint32 WriteIndex() const;
  template <class T> T Read();
  template <class T> void Write(const T& val);
private:
	TB_DISABLE_COPY_AND_ASSIGN(MemoryBuffer);
	FRIEND_TEST(MemoryBufferTest, BasicTest);
	FRIEND_TEST(MemoryBufferTest, SequenceWriteTest);
  MemoryBufferImpl* impl_;
};

template <class T>
T MemoryBuffer::Read() {
  T val;
  ReadBytes(sizeof(T), (char*)&val);
  return val;
};

template <class T>
void MemoryBuffer::Write( const T& val ) {
  WriteBytes((const char*)&val, sizeof(val));
};

typedef MemoryBuffer ReadWriteBuffer;

TB_NAMESPACE_END

#endif //CORE_BUFFER_HPP_
